package dparish.client.inject;

import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;

import dparish.client.AppActivityMapper;
import dparish.client.AppPlaceHistoryMapper;
import dparish.client.activity.StudentActivity;
import dparish.client.places.StudentListPlace;
import dparish.client.rf.PlannerRequestFactory;
import dparish.client.rf.StudentRequest;
import dparish.client.view.StudentListView;
import dparish.client.view.StudentView;
import dparish.client.view.impl.StudentListViewImpl;
import dparish.client.view.impl.StudentViewImpl;

public class MyGinModule extends AbstractGinModule {
	

	/**
	 * Configures the Gin injector classes.  
	 * There are some classes such as StudentPresenter which are declared as Singletons in the 
	 * class itself so we do not use .asEagerSingleton() in the binding.
	 */
	@Override
	protected void configure() {
		bind (EventBus.class).to(SimpleEventBus.class).asEagerSingleton(); // We only want one bus for the entire app
		bind (StudentView.class).to(StudentViewImpl.class);
		bind (StudentView.Presenter.class).to(StudentActivity.class);
		bind (StudentListView.class).to(StudentListViewImpl.class);
		bind (ActivityMapper.class).to(AppActivityMapper.class);
	}
	
	@Provides
	@Singleton
	public Place getDefaultPlace () {
		return new StudentListPlace();
	}
	
	@Provides
	public PlaceHistoryHandler getPlaceHistoryHandler (AppPlaceHistoryMapper historyMapper, PlaceController placeController, EventBus bus, Place defaultPlace) {
		PlaceHistoryHandler handler = new PlaceHistoryHandler(historyMapper);
		handler.register(placeController, bus, defaultPlace);
		return handler;
	}

	@Provides
	public ActivityManager getActivityManager (ActivityMapper mapper, EventBus bus) {
		return new ActivityManager(mapper, bus);
	}
	
	@Provides
	@Singleton
	public PlaceController getPlaceController(EventBus bus) {
		return new PlaceController (bus);
	}
	
	/**
	 * Give us the RequestFactory. None of the rest of the code needs to call this.  The Request objects such as the StudentRequest
	 * in createStudentRequestContext need it so the injector calls this class when it sees that createStudentRequest needs a
	 * PlannerRequestFactory.  
	 * @param bus This bus is provided by the EventBus binding in the configure class.
	 * @return a PlannerRequestFactory
	 */
	@Provides
	@Singleton
	private PlannerRequestFactory createPlannerRequestFactory (EventBus bus) {
		PlannerRequestFactory factory = GWT.create(PlannerRequestFactory.class);
		factory.initialize(bus);
		return factory;
	}

	/**
	 * You can't make this a singleton.  Once you've called fire() you can't call it again (or use it for create either)
	 * @see <a href="http://fascynacja.wordpress.com/tag/a-request-is-already-in-progress/">A Request is Already In Progress Error</a>
	 * @param plannerRequestFactory
	 * @return a Request Factory StudentRequest
	 */
	@Provides
	public StudentRequest createStudentRequestContext (PlannerRequestFactory plannerRequestFactory) {
		return plannerRequestFactory.studentRequest();
	}

}
